package com.gitee.wsl.ext.map

/**
 * Filters the values in this map, leaving only non-null entries
 */
@Suppress("UNCHECKED_CAST")
 fun <K, V> Map<K, V?>.filterNotNullValues(): Map<K, V & Any> = filterValues { it != null } as Map<K, V & Any>


fun <K: Any, V: Any, R: Any> Map<K, V>.mapValuesNotNull(f: (Map.Entry<K, V>) -> R?): Map<K, R> {
 return mapNotNull {
  val r = f(it)
  if (r == null) null else (it.key to r)
 }.toMap()
}


inline fun <reified R, K, V> Map<K, V>.filterIsInstanceKeys(): Map<R, V> {
 return filterIsInstanceKeysTo(LinkedHashMap())
}

inline fun <reified R, K, V, C : MutableMap<R, V>> Map<K, V>.filterIsInstanceKeysTo(destination: C): C {
 for ((key, value) in this) {
  if (key is R) destination[key] = value
 }

 return destination
}

inline fun <reified R, K, V> Map<K, V>.filterIsInstanceValues(): Map<K, R> {
 return filterIsInstanceValuesTo(LinkedHashMap())
}

inline fun <reified R, K, V, C : MutableMap<K, R>> Map<K, V>.filterIsInstanceValuesTo(destination: C): C {
 for ((key, value) in this) {
  if (value is R) destination[key] = value
 }

 return destination
}

fun <K, V : Any> Map<K, V?>.filterValuesNotNull(): Map<K, V> {
 return filterValuesNotNullTo(LinkedHashMap())
}

fun <K, V : Any, C : MutableMap<K, V>> Map<K, V?>.filterValuesNotNullTo(destination: C): C {
 return filterTo(destination as MutableMap<K, V?>) { (_, value) -> value != null } as C
}
